package cn.yto.print.service.impl;

import cn.hutool.json.JSONUtil;
import cn.yto.print.config.CaffeineCacheConfig;
import cn.yto.print.config.PrintFutureContext;
import cn.yto.print.enums.PluginRegistryEnum;
import cn.yto.print.enums.PrintCmdEnum;
import cn.yto.print.enums.ResponseCodeEnum;
import cn.yto.print.model.dto.PrintCacheDTO;
import cn.yto.print.model.request.PrintTaskRequest;
import cn.yto.print.model.request.WphPrintRequest;
import cn.yto.print.model.response.PrintTaskResponse;
import cn.yto.print.model.response.WphPrintResponse;
import cn.yto.print.plugins.SocketSessionContext;
import cn.yto.print.service.PrintConsumerService;
import cn.yto.print.service.handle.ITextMessageFunction;
import cn.yto.print.service.handle.MessageHandler;
import cn.yto.print.utils.PrintTaskUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class WphMessageHandler extends MessageHandler {

    private SocketSessionContext socketSessionContext;

    @Override
    public void initialize() {
        socketSessionContext = new SocketSessionContext(PluginRegistryEnum.WPH, createMessageHandler());
    }

    @Override
    public ITextMessageFunction createMessageHandler() {
        return (session, message) -> {
            CaffeineCacheConfig.getHeartCache().put(PluginRegistryEnum.WPH.getCode(), 1);
            WphPrintResponse wphPrintResponse;
            try {
                wphPrintResponse = JSONUtil.toBean(message.getPayload(), WphPrintResponse.class);
            } catch (Exception e) {
                log.error("唯品会打印组件回执报文解析异常，报文将丢弃~", e);
                return;
            }

            if (StringUtils.isNotEmpty(wphPrintResponse.getCmd()) && "getAgentInfo".equals(wphPrintResponse.getCmd())) {
                return;
            }
            if (StringUtils.isEmpty(wphPrintResponse.getTraceId())) {
                return;
            }
            PrintCacheDTO printCache = CaffeineCacheConfig.getPrintCache().getIfPresent(wphPrintResponse.getTraceId());
            if (null == printCache) {
                log.error("唯品会打印任务 TaskID：{} 缓存不存在，报文将丢弃~", wphPrintResponse.getTraceId());
                return;
            }
            CaffeineCacheConfig.getPrintCache().invalidate(wphPrintResponse.getTraceId());

            PrintTaskResponse printTaskResponse = new PrintTaskResponse();
            printTaskResponse.setCmd(PrintCmdEnum.NOTIFY_PRINT_RESULT.getCmd());
            printTaskResponse.setTaskId(wphPrintResponse.getTraceId());
            printTaskResponse.setSessionId(printCache.getSessionId());
            printTaskResponse.setTemplateType(printCache.getTemplateType());
            List<PrintTaskResponse.PrintStatus> printStatusList = Lists.newArrayList();
            if (200 == wphPrintResponse.getCode() || 201 == wphPrintResponse.getCode()) {
                for (WphPrintResponse.Detail detail : wphPrintResponse.getDetails()) {
                    PrintTaskResponse.PrintStatus printStatus = new PrintTaskResponse.PrintStatus();
                    if (StringUtils.isNotEmpty(detail.getStatus()) && "success".equalsIgnoreCase(detail.getStatus())) {
                        printStatus.setStatus(ResponseCodeEnum.SUCCESS.getStatus());
                    } else {
                        printStatus.setStatus(ResponseCodeEnum.FAILURE.getStatus());
                    }
                    printStatus.setDocumentID(detail.getPrintId());
                    printStatus.setMsg(detail.getMsg());
                    printStatusList.add(printStatus);
                }
            } else {
                for (String documentId : printCache.getDocumentIds()) {
                    PrintTaskResponse.PrintStatus printStatus = new PrintTaskResponse.PrintStatus();
                    printStatus.setStatus(ResponseCodeEnum.FAILURE.getStatus());
                    printStatus.setDocumentID(documentId);
                    printStatus.setMsg(wphPrintResponse.getMsg());
                    printStatusList.add(printStatus);
                }
            }
            printTaskResponse.setPrintStatus(printStatusList);
            CompletableFuture<PrintTaskResponse> future = PrintFutureContext.getResponseFuture(wphPrintResponse.getTraceId());
            if (null != future) {
                future.complete(printTaskResponse);
            } else {
                PrintConsumerService.handleTimeOutResponse(printTaskResponse);
            }
        };
    }

    @Override
    public WphPrintRequest buildPrintRequest(PrintTaskRequest pluginPrintParam) {
        WphPrintRequest wphPrintRequest = new WphPrintRequest();
        wphPrintRequest.setCmd("print");
        wphPrintRequest.setRequestID(pluginPrintParam.getTaskId());
        WphPrintRequest.Task task = new WphPrintRequest.Task();
        task.setTraceId(pluginPrintParam.getTaskId());
        task.setActionType("PRINT");
        PrintTaskRequest.Document document = pluginPrintParam.getDocuments().stream().findFirst().get();
        task.setStoreId(document.getStoreId());
        task.setChannel(document.getChannel());
        task.setPrinterName(pluginPrintParam.getPrinter());
        WphPrintRequest.PrintParamDTO printParamDTO = new WphPrintRequest.PrintParamDTO();
        List<WphPrintRequest.PrintData> printDatas = new ArrayList<>();
        pluginPrintParam.getDocuments().forEach(doc -> {
            WphPrintRequest.PrintData printData = new WphPrintRequest.PrintData();
            printData.setPrintId(doc.getDocumentID());
            printData.setPrintData(doc.getPrintData());
            printData.setCustomData(doc.getCustomData());
            printDatas.add(printData);
        });
        printParamDTO.setPrintDatas(printDatas);

        if (ObjectUtils.isNotEmpty(document.getAddData())) {
            printParamDTO.setSenderData(document.getAddData());
        }
        printParamDTO.setTemplateUrl(document.getTemplateUrl());
        printParamDTO.setCustomerTemplate(document.getCustomTempUrl());
        printParamDTO.setPlatformTemplateURL(document.getPlatformTemplateURL());
        task.setPrintParamDTO(printParamDTO);
        wphPrintRequest.setTask(task);
        return wphPrintRequest;
    }

    @Override
    public CompletableFuture<PrintTaskResponse> processMessage(PrintTaskRequest printParam) {
        WphPrintRequest wphPrintRequest = buildPrintRequest(printParam);
        socketSessionContext.sendPrintRequest(wphPrintRequest);
        PrintTaskUtil.addPrintTaskCache(printParam);
        CompletableFuture<PrintTaskResponse> completableFuture = new CompletableFuture<>();
        PrintFutureContext.addResponseFuture(printParam.getTaskId(), completableFuture);
        return completableFuture;
    }

    @Override
    public SocketSessionContext getSocketContext() {
        return socketSessionContext;
    }

}
